use std::fs;
use axum::{
    extract::Path, 
    http::{StatusCode, Uri}, 
    response::Html, 
    routing::get, 
    Router
};
use tokio::net;

struct UserAccount {
    age: u8,
    name: String,
}
impl UserAccount {
    fn from(age: u8, name: String) -> Self {
        Self {age, name}
    }
    fn to_string(&self) -> String {
        format!("age: {}, name: {}.",self.age,self.name)
    }
}


#[tokio::main]
async fn main() {
    let listener = match net::TcpListener::bind("127.0.0.1:3000").await {
        Ok(listener) => listener,
        Err(err) => panic!("Problen in {err:?}"),
    };

    let app = Router::new()
        .route("/", get(root))
        .route("/home", get(home))
        .route("/greet", get(greet))
        .fallback(fallback);

    axum::serve(listener, app).await
        .expect("Err while create serve.");
}

async fn root(uri: Uri) -> String {
    let user = UserAccount::from(18, uri.to_string());
    let message = "hello, you know i am not a well programer; it is based on unstable learning environment."
        .to_string();
    format!("{}, {}", message, user.to_string())
}

async fn home() -> Html<String> {
    Html(
        fs::read_to_string("home.html")
            .expect("Err while reading file")
    )
}

async fn fallback(uri: Uri) -> (StatusCode, String) {
    (StatusCode::NOT_FOUND, format!("Not found for {uri}."))
}

async fn greet(Path(path): Path<u32>){
    fs::write("touch.log", path.to_string())
        .expect("Err while write file");
}